﻿using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections;
using System.Text.RegularExpressions;
using XYS.Core.Models;
using XYS.Service.Core.Attributes;

namespace XYS.Service.Core.Filters
{
    /// <summary>
    /// 时间日期格式格式化
    /// </summary>
    public class DateTimeOffsetValueFilters : IActionFilter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            if (GlobalCoreSetting.FormatRequestsIgnore.Any(x => Regex.IsMatch(context.HttpContext.Request.Path.Value, "^" + Regex.Escape(x).Replace("\\*", ".*") + "$"))) return;

            var keys = context.ActionArguments.Keys.ToList();
            foreach (var key in keys)
            {
                if (context.ActionArguments[key] is string valueStringField)
                {
                    if (GlobalCoreSetting.EnableStringTrimStart || GlobalCoreSetting.EnableStringTrimEnd)
                    {
                        string trimString = TrimString(valueStringField);
                        if (trimString != valueStringField)
                            context.ActionArguments[key] = trimString;
                    }
                    continue;
                }
                FormatStartTime(context.ActionArguments[key]);
            }
        }



        private void FormatStartTime(object obj)
        {
            if (obj == null) return;
            var properties = obj.GetType().GetProperties();

            try
            {
                foreach (var property in properties)
                {
                    try
                    {
                        if (!property.CanWrite || !property.CanRead || property.GetIndexParameters().Length > 0)
                            continue;
                        var value = property.GetValue(obj);
                        if (value != null)
                        {
                            if ((GlobalCoreSetting.EnableStringTrimStart || GlobalCoreSetting.EnableStringTrimEnd) && value is string valueString)
                            {
                                string trimString = TrimString(valueString);
                                if (trimString != valueString)
                                {
                                    value = trimString;
                                    property.SetValue(obj, value);
                                }
                            }

                            var attributes = property.GetCustomAttributes(false).Where(e =>
                                e.GetType().FullName == typeof(DateTimeFormatValueAttribute).FullName
                                || e.GetType().FullName == typeof(DateTimeBeginAttribute).FullName
                                || e.GetType().FullName == typeof(DateTimeEndAttribute).FullName)
                                .ToList();

                            if (attributes.Count > 0)
                            {
                                string format = "";

                                var attribute = attributes.FirstOrDefault(e => e.GetType().FullName == typeof(DateTimeFormatValueAttribute).FullName);

                                if (attribute != null)
                                {
                                    var dateTimeOffsetValueAttribute = attribute as DateTimeFormatValueAttribute;
                                    format = dateTimeOffsetValueAttribute.Format;
                                }
                                else if (attributes.Any(e => e.GetType().FullName == typeof(DateTimeBeginAttribute).FullName))
                                {
                                    format = "yyyy-MM-dd 00:00:00";
                                }
                                else if (attributes.Any(e => e.GetType().FullName == typeof(DateTimeEndAttribute).FullName))
                                {
                                    format = "yyyy-MM-dd 23:59:59";
                                }

                                if (!string.IsNullOrEmpty(format))
                                {
                                    if (value.GetType().FullName == typeof(DateTime?).FullName || value.GetType().FullName == typeof(DateTime).FullName)
                                    {
                                        var time = value as DateTime?;
                                        if (DateTime.TryParse(time.Value.ToString(format), out var formattedTime))
                                        {
                                            property.SetValue(obj, formattedTime);
                                        }
                                    }
                                    else if (value.GetType().FullName == typeof(string).FullName)
                                    {
                                        if (DateTime.TryParse(value.ToString(), out var time))
                                        {
                                            property.SetValue(obj, time.ToString(format));
                                        }
                                    }
                                }
                            }

                            if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType) && property.PropertyType != typeof(string))
                            {
                                var enumerable = (IEnumerable)property.GetValue(obj);
                                if (enumerable != null)
                                {
                                    foreach (var item in enumerable)
                                    {
                                        FormatStartTime(item);
                                    }
                                }
                            }
                            else if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType != typeof(byte[]))// Recursive call for nested objects
                            {
                                var nestedObject = property.GetValue(obj);
                                if (nestedObject != null)
                                {
                                    FormatStartTime(nestedObject);
                                }
                            }
                            else if (property.PropertyType.IsArray)// Recursive call for array elements
                            {
                                if (property.GetValue(obj) is Array array)
                                {
                                    foreach (var element in array)
                                    {
                                        FormatStartTime(element);
                                    }
                                }
                            }
                        }
                    }
                    catch { }
                }
            }
            catch { }
        }


        private string TrimString(string str)
        {
            string trimString = str;

            if (GlobalCoreSetting.EnableStringTrimStart) trimString = trimString.TrimStart();
            if (GlobalCoreSetting.EnableStringTrimEnd) trimString = trimString.TrimEnd();

            return trimString;
        }




        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuted(ActionExecutedContext context)
        {
            // Do nothing
        }

    }



}
